package bb.lanxing.device.sync;

import com.garmin.fit.RecordMesg;
import com.garmin.fit.SessionMesg;
import com.garmin.fit.Sport;
import bb.lanxing.calc.data.CadencePoint;
import bb.lanxing.calc.data.GpsPoint;
import bb.lanxing.calc.data.HeartratePoint;
import bb.lanxing.calc.data.SourcePoint;
import bb.lanxing.model.database.Device;
import bb.lanxing.model.database.Workout;

public class FitHelper {
    public static final int SOURCE_TYPE_NONE = 0;
    public static final int SOURCE_TYPE_IGPS = 1;
    public static final int SOURCE_TYPE_BRYTON = 2;
    public static final int SOURCE_TYPE_SPRINT = 3;
    public static final int SOURCE_TYPE_DISCOVERY = 4;
    public static final int SOURCE_TYPE_XOSS_G = 5;
    public static final int SOURCE_TYPE_BES_WATCH = 6;
    public static final int SOURCE_TYPE_GARMIN = 8;
    public static final int SOURCE_TYPE_XOSS_G_PLUS = 13;
    public static final int SOURCE_TYPE_CYCPLUS_M1 = 16;
    public static final int SOURCE_TYPE_CYCPLUS_M2 = 17;
    public static final int SOURCE_TYPE_XOSS_NAV = 18;
    public static final int SOURCE_TYPE_CHILEAF_600 = 19;
    public static final int SOURCE_TYPE_XOSS_X2P = 20;
    public static final int SOURCE_TYPE_XOSS_NAV_PLUS = 21;

    private static int getCadenceSource(int sourceType) {
        return switch (sourceType) {
            case SOURCE_TYPE_IGPS -> Workout.CADENCE_SOURCE_IGPS;
            case SOURCE_TYPE_BRYTON -> Workout.CADENCE_SOURCE_BRYTON;
            case SOURCE_TYPE_SPRINT -> Workout.CADENCE_SOURCE_SPRINT;
            default -> Workout.CADENCE_SOURCE_OTHER;
        };
    }

    private static int getHeartrateSource(int sourceType) {
        return switch (sourceType) {
            case SOURCE_TYPE_IGPS -> Workout.HEARTRATE_SOURCE_IGPS;
            case SOURCE_TYPE_BRYTON -> Workout.HEARTRATE_SOURCE_BRYTON;
            case SOURCE_TYPE_SPRINT -> Workout.HEARTRATE_SOURCE_SPRINT;
            case SOURCE_TYPE_XOSS_X2P -> Workout.HEARTRATE_SOURCE_XOSS_X2P;
            default -> Workout.HEARTRATE_SOURCE_OTHER;
        };
    }

    private static int getLocationSource(int sourceType) {
        return switch (sourceType) {
            case SOURCE_TYPE_IGPS -> Workout.LOCATION_SOURCE_IGPS;
            case SOURCE_TYPE_BRYTON -> Workout.LOCATION_SOURCE_BRYTON;
            case SOURCE_TYPE_SPRINT -> Workout.LOCATION_SOURCE_SPRINT;
            case SOURCE_TYPE_DISCOVERY -> Workout.LOCATION_SOURCE_DISCOVERY;
            case SOURCE_TYPE_XOSS_G -> Workout.LOCATION_SOURCE_XOSS_G;
            case SOURCE_TYPE_CYCPLUS_M1 -> Workout.LOCATION_SOURCE_CYCPLUS_M1;
            case SOURCE_TYPE_CYCPLUS_M2 -> Workout.LOCATION_SOURCE_CYCPLUS_M2;
            case SOURCE_TYPE_XOSS_NAV -> Workout.LOCATION_SOURCE_XOSS_NAV;
            case SOURCE_TYPE_CHILEAF_600 -> Workout.LOCATION_SOURCE_CHILEAF_600;
            case SOURCE_TYPE_XOSS_X2P -> Workout.LOCATION_SOURCE_XOSS_X2P;
            default -> Workout.LOCATION_SOURCE_OTHER;
        };
    }

    public static int getSourceType(int deviceType) {
        return switch (deviceType) {
            case Device.TYPE_WINGS -> SOURCE_TYPE_SPRINT;
            case Device.TYPE_DISCOVERY -> SOURCE_TYPE_DISCOVERY;
            case Device.TYPE_XOSS_G -> SOURCE_TYPE_XOSS_G;
            case Device.TYPE_HR_X2_PRO -> SOURCE_TYPE_XOSS_X2P;
            case Device.TYPE_IGPS -> SOURCE_TYPE_IGPS;
            case Device.TYPE_BRYTEN -> SOURCE_TYPE_BRYTON;
            case Device.TYPE_CHILEAF_600 -> SOURCE_TYPE_CHILEAF_600;
            case Device.TYPE_XOSS_NAV -> SOURCE_TYPE_XOSS_NAV;
            default -> SOURCE_TYPE_NONE;
        };
    }

    public static SourcePoint createSourcePointByFitMesg(RecordMesg recordMesg, int sourceType) {
        CadencePoint cadencePoint;
        GpsPoint gpsPoint = new GpsPoint();
        gpsPoint.setSource(getLocationSource(sourceType));
        if (recordMesg.getPositionLat() != null) {
            gpsPoint.setLatitude(toDegrees(recordMesg.getPositionLat()));
        }
        if (recordMesg.getPositionLong() != null) {
            gpsPoint.setLongitude(toDegrees(recordMesg.getPositionLong()));
        }
        if (recordMesg.getAltitude() != null) {
            gpsPoint.setAltitude(recordMesg.getAltitude());
        }
        if (recordMesg.getSpeed() != null) {
            gpsPoint.setSpeed(recordMesg.getSpeed());
        }
        if (recordMesg.getTimestamp() != null) {
            gpsPoint.setTimestamp(recordMesg.getTimestamp().getDate().getTime());
        }
        HeartratePoint heartratePoint = null;
        if (recordMesg.getCadence() == null || recordMesg.getCadence() <= 0) {
            cadencePoint = null;
        } else {
            cadencePoint = new CadencePoint();
            cadencePoint.setCadence(recordMesg.getCadence());
            if (recordMesg.getSpeed() != null) {
                cadencePoint.setSpeed(recordMesg.getSpeed());
            }
            cadencePoint.setSource(getCadenceSource(sourceType));
        }
        if (recordMesg.getHeartRate() != null && recordMesg.getHeartRate() > 0) {
            heartratePoint = new HeartratePoint();
            heartratePoint.setHeartrate(recordMesg.getHeartRate());
            heartratePoint.setSource(getHeartrateSource(sourceType));
        }
        SourcePoint sourcePoint = new SourcePoint();
        sourcePoint.setGpsPoint(gpsPoint);
        sourcePoint.setCadencePoint(cadencePoint);
        sourcePoint.setHeartratePoint(heartratePoint);
        if (recordMesg.getPower() != null) {
            sourcePoint.setPower(recordMesg.getPower());
        }
        return sourcePoint;
    }

    public static void sessionMesgToWorkout(SessionMesg sessionMesg, Workout workout, int sourceType) {
        if (sessionMesg.getStartTime() != null) {
            workout.setStartTime(sessionMesg.getStartTime().getDate().getTime());
        }
        if (sessionMesg.getTotalMovingTime() != null) {
            workout.setDuration(sessionMesg.getTotalMovingTime().intValue());
        } else if (sessionMesg.getTotalTimerTime() != null) {
            workout.setDuration(sessionMesg.getTotalTimerTime().intValue());
        }
        if (sessionMesg.getTotalDistance() != null) {
            workout.setDistance(sessionMesg.getTotalDistance());
        }
        if (sessionMesg.getTotalCalories() != null) {
            workout.setCalorie(sessionMesg.getTotalCalories() * 1000);
        }
        if (sessionMesg.getAvgSpeed() != null) {
            workout.setAvgSpeed(sessionMesg.getAvgSpeed());
        }
        if (sessionMesg.getMaxSpeed() != null) {
            workout.setMaxSpeed(sessionMesg.getMaxSpeed());
        }
        if (sessionMesg.getAvgHeartRate() != null) {
            workout.setAvgHeartrate(sessionMesg.getAvgHeartRate());
        }
        if (sessionMesg.getMaxHeartRate() != null) {
            workout.setMaxHeartrate(sessionMesg.getMaxHeartRate());
        }
        if (sessionMesg.getAvgCadence() != null) {
            workout.setAvgCadence(sessionMesg.getAvgCadence());
        }
        if (sessionMesg.getMaxCadence() != null) {
            workout.setMaxCadence(sessionMesg.getMaxCadence());
        }
        if (sessionMesg.getTotalAscent() != null) {
            workout.setElevationGain(sessionMesg.getTotalAscent());
        }
        if (sessionMesg.getTotalDescent() != null) {
            workout.setElevationLoss(sessionMesg.getTotalDescent());
        }
        if (sessionMesg.getTimestamp() != null) {
            workout.setEndTime(sessionMesg.getTimestamp().getDate().getTime());
        }
        if (workout.getAvgCadence() > 0) {
            workout.setCadenceSource(Workout.CADENCE_SOURCE_OTHER);
        }
        if (workout.getAvgHeartrate() > 0) {
            workout.setHeartSource(Workout.HEARTRATE_SOURCE_OTHER);
        }
        if (sessionMesg.getMaxPower() != null && sessionMesg.getMaxPower() > 0) {
            workout.setMaxPower(sessionMesg.getMaxPower());
            workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
        }
        if (sessionMesg.getNormalizedPower() != null) {
            workout.setPowerNP(sessionMesg.getNormalizedPower());
        }
        if (sessionMesg.getIntensityFactor() != null) {
            workout.setPowerIF(sessionMesg.getIntensityFactor());
        }
        if (sessionMesg.getTrainingStressScore() != null) {
            workout.setPowerTSS(sessionMesg.getTrainingStressScore());
        }
        if (sessionMesg.getAvgPower() != null) {
            workout.setAvgPower(sessionMesg.getAvgPower());
        }
        if (sessionMesg.getNormalizedPower() != null && sessionMesg.getAvgPower() != null) {
            workout.setPowerVI((double) sessionMesg.getNormalizedPower() / sessionMesg.getAvgPower());
        }
        workout.setLocSource(getLocationSource(sourceType));
        workout.setWorkStatus(Workout.STATUS_STOPED);//32
    }

    public static void sportTypeToWorkout(SessionMesg sessionMesg, Workout workout) {
        if (sessionMesg.getSport() != null) {
            if (sessionMesg.getSport() == Sport.WALKING) {
                workout.setSport(Workout.TYPE_WALKING);
            } else if (sessionMesg.getSport() == Sport.RUNNING) {
                workout.setSport(Workout.TYPE_RUNNING);
            } else if (sessionMesg.getSport() == Sport.CYCLING) {
                if (sessionMesg.getSubSport() != null && sessionMesg.getSubSport().getValue() == 6) {
                    workout.setSport(Workout.TYPE_INDOOR_BIKE);
                } else {
                    workout.setSport(Workout.TYPE_CYCLING);
                }
            } else if (sessionMesg.getSport() == Sport.TRAINING) {
                workout.setSport(Workout.TYPE_TRAINING);
            }else {
                workout.setSport(Workout.TYPE_OTHER);
            }
        }
    }

    private static double toDegrees(Integer num) {
        return num * (180.0d / Math.pow(2.0d, 31.0d));
    }
}
